#include "LinAlg.h"
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
Vector3::Vector3(){
x=0.0; y=0.0; z=0.0;
}

Vector3::Vector3(float x0,float y0,float z0){
x=x0; y=y0; z=z0;
}

void Vector3::set(float x0,float y0,float z0){
x=x0; y=y0; z=z0;
}

void Vector3::set(Vector3 &a){
x = a.x;
y = a.y;
z = a.z;
}

void Vector3::add(Vector3 &a){
x+=a.x; y+=a.y; z+=a.z;
}

void Vector3::add(Vector3 &a,Vector3 &b){
x=a.x+b.x; y=a.y+b.y; z=a.z+b.z;
}

void Vector3::subtract(Vector3 &a){
x-=a.x; y-=a.y; z-=a.z;
}

void Vector3::subtract(Vector3 &a,Vector3 &b){
x=a.x-b.x; y=a.y-b.y; z=a.z-b.z;
}

void Vector3::negate(){
x=-x; y=-y; z=-z;
}

void Vector3::negate(Vector3 &a){
x=-a.x; y=-a.y; z=-a.z;
}

void Vector3::scale(float s){
x*=s; y*=s; z*=s;
}

void Vector3::scale(float s,Vector3 &a){
x=s*a.x; y=s*a.y; z=s*a.z;
}

float Vector3::dot(Vector3 &a){
return x*a.x+y*a.y+z*a.z;
}

void Vector3::cross(Vector3 &a,Vector3 &b){
float x =a.y*b.z-a.z*b.y; 
float y =a.z*b.x-a.x*b.z; 
float z =a.x*b.y-a.y*b.x;
this->x = x;
this->y = y;
this->z = z;
}

float Vector3::magnitude(){
return sqrt((x*x)+(y*y)+(z*z));
}

float Vector3::length(){
return magnitude();
}

void Vector3::normalize(){
scale(1.0/magnitude());
}

Vector3 Vector3::divide(Vector3 &a){
	Vector3 res;
	res.x = x / a.x;
	res.y = y / a.y;
	res.z = z / a.z;
	return res;
}

float Vector3::angleBetween(Vector3 &v1, Vector3 &v2){
	Vector3 a, b;
	float res;
	a.set(v1);
	b.set(v2); 
	a.scale(1.0/a.length()); 
	b.scale(1.0/b.length()); 
	res = a.dot(b);
	if(res > 1)
		res = 1;
	if(res < -1)
		res = -1;
	return acos(res);
}

float Vector3::get(char a){
if(a == 'a')
  return x;
if(a == 'b')
  return y;
if(a == 'c')
  return z;
return 0.0;
}

float* Vector3::get(){
float* res = (float*) malloc(4);
res[0] = x;
res[1] = y;
res[2] = z;
return res;
}

// vector array index operator overload
float Vector3::operator[](int i){
return get()[i];
}

// vector addition operator overload
Vector3& Vector3::operator+(Vector3 &c){
Vector3 *res = new Vector3;
res->add(c, *this);
return *res;
}

// vector subtraction operator overload
Vector3& Vector3::operator-(Vector3 &c){
Vector3 *res = new Vector3;
res->subtract(*this, c);
return *res;
}

// vector multiplication operator overload
Vector3& Vector3::operator*(Vector3 &c){
Vector3 *res = new Vector3;
res->set(*this);
res->dot(c);
return *res;
}

Vector3& Vector3::operator*(float c){
Vector3 *res = new Vector3();
res->set(*this);
res->scale(c);
return *res;
}

Vector3& Vector3::operator/(float c){
this->scale(1.0/c);
return *this;
}

// vector assignment overload
void Vector3::operator=(Vector3 &c){
this->set(c);
}
/*
void Vector3::operator=(Vector3 c){
this->set(c);
}
*/
void Vector3::printVector(){
	printf("\tX: %.2f, Y: %.2f, Z: %.2f\n",x,y,z);
}

bool Vector3::equals(Vector3* v){
	if(x == v->x)
	  if(y == v->y)
	  	if(z == v->z)
	  		return true;
	return false;
}

